/*
 *  testClassHeap.cpp
 *  kangmodb
 *
 *  Created by 강모 김 on 11. 4. 25..
 *  Copyright 2011 강모소프트. All rights reserved.
 *
 */



#include "gtest/gtest.h"

#include "kangmodb.h"
#include "testCommon.h"
#include "heap.h"

/** @brief Test kdHeap class 
 */
class ClassHeapTest : public testing::Test {
protected:  // You should make the members protected s.t. they can be
	// accessed from sub-classes.
	
	// virtual void SetUp() will be called before each test is run.  You
	// should define it if you need to initialize the varaibles.
	// Otherwise, this can be skipped.
	virtual void SetUp() {
	}
	
	// virtual void TearDown() will be called after each test is run.
	// You should define it if there is cleanup work to do.  Otherwise,
	// you don't have to provide it.
	//
	virtual void TearDown() {
	}
protected:
};


typedef struct test_data_t
{
	char data[1];
} test_data_t;

// A heap with u64 type key and test_data_t* type for data
typedef kdHeap<u64, test_data_t*> TestHeap;

void ExpectMinMax( const TestHeap & heap, int nMin, int nMax )
{
	u64 key;
	
	// Min key value should be 1
	EXPECT_TRUE( heap.getMin( &key ) == 0);
	EXPECT_EQ( key, nMin );

	// Max key value should be 5
	EXPECT_TRUE( heap.getMax( &key ) == 0);
	EXPECT_EQ( key, nMax );
}



TEST_F(ClassHeapTest, Basic) {
	test_data_t data1 = { {'1'} };
	test_data_t data2 = { {'2'} };
	test_data_t data3 = { {'3'} };
	test_data_t data4 = { {'4'} };
	test_data_t data5 = { {'5'} };
	
	TestHeap heap;
	
	// Should be empty.
	EXPECT_TRUE( heap.empty() );
	
	// Add an item
	EXPECT_TRUE( heap.add(1, &data1) == 0 );
	 
	// Should not be empty.
	EXPECT_FALSE( heap.empty() );
	
	// Both Min key and Max key value should be 1
	ExpectMinMax( heap, 1, 1);

	// Removing (key,data) pair that does not exist.
	// => Succeeds, but nothing is removed.
	EXPECT_TRUE( heap.remove(1, &data2) == 0 );
	
	// Should not be empty.
	EXPECT_FALSE( heap.empty() );
	
	// Removing (key,data) pair that exists.
	EXPECT_TRUE( heap.remove(1, &data1) == 0 );
	
	// Should be empty.
	EXPECT_TRUE( heap.empty() );

	// Add an item again
	// Add an items 1,2,3,4,5
	EXPECT_TRUE( heap.add(1, &data1) == 0 );
	EXPECT_TRUE( heap.add(3, &data3) == 0 );
	EXPECT_TRUE( heap.add(2, &data2) == 0 );
	EXPECT_TRUE( heap.add(5, &data5) == 0 );
	EXPECT_TRUE( heap.add(4, &data4) == 0 );
	// Should not be empty.
	EXPECT_FALSE( heap.empty() );

	// Min key should be 1, Max key should be 5
	ExpectMinMax( heap, 1, 5);

	// Remove 4, Max should still be 5, Min should still be 1
	EXPECT_TRUE( heap.remove(4, &data4) == 0 );
	ExpectMinMax( heap, 1, 5);

	// Remove 5, Max should be 3, Min should still be 1
	EXPECT_TRUE( heap.remove(5, &data5) == 0 );
	ExpectMinMax( heap, 1, 3);

	// Remove 1, Max should be 3, Min should still be 2
	EXPECT_TRUE( heap.remove(1, &data1) == 0 );
	ExpectMinMax( heap, 2, 3);

	// Remove 2, Max should be 3, Min should still be 3
	EXPECT_TRUE( heap.remove(2, &data2) == 0 );
	ExpectMinMax( heap, 3, 3);

	// Should not empty.
	EXPECT_FALSE( heap.empty() );
	
	// Remove 3
	EXPECT_TRUE( heap.remove(3, &data3) == 0 );
	// TODO : Add test case : getMin, getMax hits Assertion, because there is no items.
	
	// Should be empty.
	EXPECT_TRUE( heap.empty() );
}




